package com.lez.flowpractice2.download

import com.lez.flowpractice2.utils.copyToTwo
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.flow
import okhttp3.OkHttpClient
import okhttp3.Request
import java.io.File
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flowOn
import java.io.IOException

//object 是对象声明，表明是单例的
//下载管理器
object DownloadManager {

    fun download(url: String,file: File): Flow<DownloadStates> {

        return flow {
            val request = Request.Builder().url(url).get().build()
            val response = OkHttpClient.Builder().build().newCall(request).execute()
            if(response.isSuccessful){
                response.body()!!.let { body ->
                    val total = body.contentLength()
                    //文件读写
                    file.outputStream().use { output ->   //use函数实现了Closeable接口的对象，use函数会自动关闭调用者
                        val input = body.byteStream()
                        var emittedProgress = 0L
                        input.copyToTwo(output){ bytesCopied ->
                            val progress = bytesCopied * 100 / total
                            emit(DownloadStates.Progress(progress.toInt()))
                            emittedProgress = progress
                        }
                    }
                    emit(DownloadStates.Done(file))
                }
            }else{
                throw IOException(response.toString())
            }

        }.catch {
            file.delete()
            emit(DownloadStates.Error(it))
        }.flowOn(Dispatchers.IO)    //默认情况下 流的发射和流的收集都必须在同一个上下文，使用flowOn可以更改流发射的上下文
    }
}